package utils

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"strconv"
	"strings"

	"github.com/gofrs/uuid"
)

func StringToInt(str string) int {
	i, _ := strconv.Atoi(str)
	return i
}

func StringToInt64(str string) int64 {
	i, _ := strconv.ParseInt(str, 10, 64)
	return i
}

func Float64ToFloat64(str string, num float64) float64 {
	result := fmt.Sprintf(str, num)
	num, _ = strconv.ParseFloat(result, 64)
	return num
}

func Float64sToString(floats []float64) string {
	strs := make([]string, len(floats))
	for i, f := range floats {
		strs[i] = fmt.Sprintf("%.2f", f)
	}
	return strings.Join(strs, ",")
}

func StringToFloat64(str string) float64 {
	num, _ := strconv.ParseFloat(str, 64)
	return num
}

func IntToString(i int) string {
	return strconv.Itoa(i)
}

func Int64ToString(i int64) string {
	return strconv.FormatInt(i, 10)
}

func Base64UrlSafeEncode(str string) string {
	return base64.URLEncoding.EncodeToString([]byte(str))
}

func Base64UrlSafeDecode(str string) string {
	data, err := base64.URLEncoding.DecodeString(str)
	if err != nil {
		log.Println("base decode error :" + err.Error())
		return ""
	}
	return string(data)
}

func MD5(v string) string {
	d := []byte(v)
	m := md5.New()
	m.Write(d)
	return hex.EncodeToString(m.Sum(nil))
}

func CompareHmacString(secret, signEncodedData, encodedData string) bool {
	tbyte, _ := base64.URLEncoding.DecodeString(signEncodedData)
	h := hmac.New(sha1.New, []byte(secret))
	h.Write([]byte(encodedData))

	return hmac.Equal(h.Sum(nil), tbyte)
}

func RandStr(n int) string {
	var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

func FormatColumn(prefix string, deviceFieldNames []string) string {
	rows := []string{}
	for _, v := range deviceFieldNames {
		rows = append(rows, prefix+"."+v)
	}
	return strings.Join(rows, ",")
}

func GetFileName() string {
	u1, _ := uuid.NewV4()
	return strings.Replace(u1.String(), "-", "", -1)
}

func SplitValue(str string, split string, key int) string {
	strs := strings.Split(str, split)
	if len(strs) > key {
		return strs[key]
	} else {
		return ""
	}
}

func StringArrayKey(list []string, value string) bool {
	for _, v := range list {
		if v == value {
			return true
		}
	}
	return false
}

func Int64ArrayKey(list []int64, value int64) bool {
	for _, v := range list {
		if v == value {
			return true
		}
	}
	return false
}

// func InArray(val string, values string) bool {
// 	if values == "" {
// 		return true
// 	}
// 	for _, v := range strings.Split(values, ",") {
// 		if val == v {
// 			return true
// 		}
// 	}
// 	return false
// }

func InArray[T comparable](elem T, data []T, isEmpty bool) bool {
	if len(data) == 0 {
		return isEmpty
	}
	for _, v := range data {
		if any, ok := interface{}(v).(string); ok {
			// 这里我们尝试将v转换为string类型进行比较，但这并不是泛型推荐的使用方式。
			if any == "" {
				return isEmpty
			}
		}
		if v == elem {
			return true
		}
	}
	return false
}

func StringToStruct(jsonStr string, obj interface{}) error {
	err := json.Unmarshal([]byte(jsonStr), obj)
	if err != nil {
		return err
	}
	return nil
}

func StructToString(obj interface{}) (string, error) {
	jsonStr, err := json.Marshal(obj)
	if err != nil {
		return "", err
	}
	return string(jsonStr), nil
}
